﻿using Hazdryx.Drawing;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;

namespace EmotionsExtract.UITex
{
    public class UITexFile : IDisposable
    {
        /// <summary>
        /// 图像文件宽度
        /// </summary>
        public int ImageWidth { get; private set; }

        /// <summary>
        /// 图像文件高度
        /// </summary>
        public int ImageHeight { get; private set; }

        /// <summary>
        /// 静态帧数量（包括空的与被动画引用的帧）
        /// </summary>
        public int FrameCount { get; private set; }

        /// <summary>
        /// 动画数量
        /// </summary>
        public int AnimationCount { get; private set; }

        /// <summary>
        /// 图像
        /// </summary>
        public FastBitmap Image { get; private set; }

        /// <summary>
        /// 所有静态帧
        /// </summary>
        public Frame[] Frames { get; private set; }

        /// <summary>
        /// 所有不为空且未被动画引用的静态帧
        /// </summary>
        public Frame[] StaticFrames { get => this.Frames.Where(i => i != null && !i.UsedByAnimation).ToArray(); }

        /// <summary>
        /// 所有动画
        /// </summary>
        public Animation[] Animations { get; private set; }

        /// <summary>
        /// 加载 UITex 文件
        /// </summary>
        /// <param name="path">UITex 文件名</param>
        /// <returns></returns>
        /// <exception cref="InvalidDataException">UITex 文件头部无效</exception>
        /// <exception cref="FileNotFoundException">对应的图像文件不存在</exception>
        public static UITexFile Load(string path)
        {
            UITexFile uiTex = new UITexFile();
            using(FileStream fs = new FileStream(path, FileMode.Open))
            using(BinaryReader br = new BinaryReader(fs))
            {
                // 读取文件头
                Int16 magic = br.ReadInt16();
                if(magic != 0x4955)
                    throw new InvalidDataException("文件头错误：" + Encoding.ASCII.GetString(BitConverter.GetBytes(magic)));
                int uiTexType = br.ReadInt16(); // 0=动画无延迟 1=动画有延迟 2=？？？（看下面）
                uiTex.ImageWidth = br.ReadInt32();
                uiTex.ImageHeight = br.ReadInt32();
                uiTex.FrameCount = br.ReadInt32();
                uiTex.AnimationCount = br.ReadInt32();
                br.ReadInt32(); // file length

                // 读取图像文件
                string uitexDir = Path.GetDirectoryName(path);
                string imageFileName = Path.Combine(uitexDir, Encoding.GetEncoding(936).GetString(br.ReadBytes(64)).TrimEnd('\0'));
                imageFileName = Path.ChangeExtension(imageFileName, null);
                if(File.Exists($"{imageFileName}.tga"))
                    imageFileName = $"{imageFileName}.tga";
                else if(File.Exists($"{imageFileName}.dds"))
                    imageFileName = $"{imageFileName}.dds";
                else
                    throw new FileNotFoundException("图片文件不存在：" + imageFileName);
                uiTex.Image = ImageUtils.LoadTexture(imageFileName);

                // 读取所有静态帧
                uiTex.Frames = new Frame[uiTex.FrameCount];
                for(int i = 0; i < uiTex.FrameCount; i++)
                {
                    int info = br.ReadInt32();
                    int left = br.ReadInt32();
                    int top = br.ReadInt32();
                    int width = br.ReadInt32();
                    int height = br.ReadInt32();
                    uiTex.Frames[i] = (width == 0 && height == 0) ? null : new Frame(i, uiTex, info, left, top, width, height);
                }

                // 读取所有动画
                if (uiTexType == 2)
                    br.ReadInt32();     // ？？？
                int animationIdx = 0;
                List<Animation> animations = new List<Animation>();
                while(br.BaseStream.Position < br.BaseStream.Length)
                {
                    int animationFrameCount = br.ReadInt32();
                    if (animationFrameCount == 0)
                    {
                        animations.Add(null);
                    }
                    else
                    {
                        AnimationFrame[] animationFrames = new AnimationFrame[animationFrameCount];
                        for (int i = 0; i < animationFrameCount; i++)
                        {
                            int frameIndex = br.ReadInt32();
                            int delay = uiTexType != 0 ? br.ReadInt32() : 100;
                            animationFrames[i] = new AnimationFrame(uiTex.Frames[frameIndex], delay);
                        }
                        animations.Add(new Animation(animationIdx, animationFrames));
                    }
                    ++animationIdx;
                }
                uiTex.Animations = animations.ToArray();
                return uiTex;
            }
        }

        public void Dispose()
        {
            this.Image.Dispose();
        }

        ~UITexFile()
        {
            this.Dispose();
        }
    }
}
